<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Argentina</title>
<style type="text/css">
html,body{margin:0;padding:0;border:0}
body{background-color:#FFFFFF;cursor:default;overflow:hidden}
body{font-family:tahoma,arial,sans-serif;font-size:9pt;}
</style>
</head>
<body>
<div id="detail" style="display:none">
<textarea id="appids" style="position: absolute; margin-left: 0px; margin-right: 0px; width: 419px; margin-top: 0px; margin-bottom: 0px; height: 172px; left: 51px; top: 145px; "></textarea>
<span style="position: absolute; left: 13px; top: 155px; width: 33px; height: 14px; ">appid列表</span>
<span style="position: absolute; width: 6px; height: 50px; left: 285px; top: 101px; ">port:</span>
<input id="port" type="text" style="position: absolute; left: 322px; top: 97px; width: 52px; height: 19px; " value="8087">
<span style="position: absolute; width: 55px; height: 19px; left: 8px; top: 62px; ">host:</span>
<input id="gae_addr" type="text" style="position: absolute; left: 52px; top: 58px; width: 204px; height: 24px; " value="www.google.com.ar">
<input id="app_path" type="text" style="position: absolute; left: 55px; top: 96px; width: 117px; height: 22px; " value="/2?">
<span style="position: absolute; left: 10px; top: 112px; width: 29px; height: 13px; ">path:</span>
<button id="get_cur_appid" style="position: absolute; width: 130px; height: 34px; left: 201px; top: 335px; ">查看当前appid</button>
<button id="remove_cur_appid" style="position: absolute; width: 129px; height: 33px; left: 349px; top: 337px; ">更换当前appid</button>
<button id="change_gae_app_path" style="position: absolute; width: 78px; height: 28px; left: 183px; top: 96px; ">更改</button>
<button id="change_gae_addr" style="position: absolute; width: 69px; height: 29px; left: 276px; top: 56px; ">更改</button>
<button id="change_appids" style="position: absolute; width: 100px; height: 33px; left: 50px; top: 335px; ">应用appid列表</button>
<button id="set_proxy_auto" style="position: absolute; left: 141px; top: 10px; width: 107px; height: 34px; ">自动设置代理</button>
<button id="set_proxy_man" style="position: absolute; left: 252px; top: 11px; width: 108px; height: 33px; ">手动设置代理</button>
<button id="enable_proxy" style="position: absolute; left: 372px; top: 11px; width: 90px; height: 32px; ">启用代理</button>
<button id="disable_proxy" style="position: absolute; left: 371px; top: 52px; width: 91px; height: 31px; ">禁用代理</button>
<button id="install_cert" style="position: absolute; left: 490px; top: 10px; width: 120px; height: 31px; ">导入证书</button>
<button id="uninstall_cert" style="position: absolute; width: 122px; height: 32px; left: 490px; top: 53px; ">撤销证书</button>

</div>

<div style="position: absolute; background-color: red; width: 100px; height: 12px; left: 497px; top: 154px; "></div>
<div style="position: absolute; background-color: red; width: 101px; height: 13px; left: 498px; top: 261px; "></div>
<div style="position: absolute; background-color: red; width: 98px; height: 13px; left: 498px; top: 232px; "></div>
<div style="position: absolute; background-color: red; width: 99px; height: 13px; left: 498px; top: 205px; "></div>
<div style="position: absolute; background-color: red; width: 100px; height: 12px; left: 498px; top: 180px; "></div>

<a id="show_hide_detail" style="position: absolute; width: 113px; height: 12px; left: 16px; top: 20px; " href="javascript:;">显示/隐藏细节设置</a>
<button id="auto_conf" style="position: absolute; width: 92px; height: 39px; left: 204px; top: 163px; z-index: -1">开始</button>
<div id="argentina" style="position: absolute; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); width: 123px; height: 155px; left: 485px; top: 132px; "></div>

<span style="position: absolute; width: 152px; height: 14px; left: 47px; top: 390px; ">母体版本: 0.1.0.419</span>
<a id="readme" style="position: absolute; left: 215px; top: 389px; width: 77px; height: 14px; " href="javascript:;">非正式说明</a>
<a style="position: absolute; width: 50px; height: 14px; left: 385px; top: 390px; " target="_blank" href="https://code.google.com/p/milkline">项目主页</a>

<script type="text/javascript" src="readme.js" id="sc_readme"></script>
<script type="text/javascript" src="appids.js" id="sc_default_appids"></script>
<script type="text/javascript" id="sc_declaration">
////////// lmk //////////
var lmk = {
    obj: function () {
        return external(0, 0);
    },
    hMod: function () {
        return external(0, 1);
    },
    hApp: function () {
        return external(0, 2);
    },

    lib: function (lib_name) {
        return external(1, lib_name);
    },
    func: function (lib, func_name) {
        return external(1, lib, func_name);
    },

    callback: function (obj, func_name, arg_count, is_cdecl, cross_thread) {
        return external(3, obj, func_name, arg_count, is_cdecl, cross_thread);
    },
    clearCallback: function (callback_address) {
        return external(3, callback_address);
    },

    free: function (memory) {
        return external(4, 0, memory);
    },
    malloc: function (size) {
        return external(4, 1, size);
    },
    calloc: function (num, size) {
        return external(4, 2, num, size);
    },
    realloc: function (memory, newsize) {
        return external(4, 3, memory, newsize);
    },
    memset: function (dst, val, size) {
        return external(4, 4, dst, val, size);
    },
    memcpy: function (dst, src, size) {
        return external(4, 5, dst, src, size);
    },
    memmove: function (dst, src, size) {
        return external(4, 6, dst, src, size);
    },
    memcmp: function (buf1, buf2, size) {
        return external(4, 7, buf1, buf2, size);
    },

    byte: function (ptr) {
        return external(5, 1, ptr);
    },
    word: function (ptr) {
        return external(5, 2, ptr);
    },
    dword: function (ptr) {
        return external(5, 4, ptr);
    },
    setByte: function (ptr, value) {
        return external(5, 1, ptr, value);
    },
    setWord: function (ptr, value) {
        return external(5, 2, ptr, value);
    },
    setDword: function (ptr, value) {
        return external(5, 4, ptr, value);
    },

    bstr: function (ptr) {
        return external(6, 0, ptr);
    },
    strw: function (ptr) {
        return external(6, 1, ptr);
    },
    stra: function (ptr) {
        return external(6, 2, ptr);
    },
    stru: function (ptr) {
        return external(6, 3, ptr);
    },
    strwl: function (ptr, len) {
        return external(6, 1, ptr, len);
    },
    stral: function (ptr, len) {
        return external(6, 2, ptr, len);
    },
    strul: function (ptr, len) {
        return external(6, 3, ptr, len);
    },

    setStrw: function (ptr, str) {
        return external(7, 1, ptr, str);
    },
    setStra: function (ptr, str) {
        return external(7, 2, ptr, str);
    },
    setStru: function (ptr, str) {
        return external(7, 3, ptr, str);
    },
    newStrw: function (str) {
        return external(7, 1, 0, str);
    },
    newStra: function (str) {
        return external(7, 2, 0, str);
    },
    newStru: function (str) {
        return external(7, 3, 0, str);
    },

    data: function (ptr, len) {
        return external(6, 4, ptr, len);
    },
    setData: function (ptr, data) {
        return external(7, 4, ptr, data);
    },
    newData: function (data) {
        return external(7, 4, 0, data);
    }
}

////////// module main //////////
var _fn_Windy_set_on_close = external(1, -1, "Windy_set_on_close");
function Windy_set_on_close(windy, value) {
    return external(2, 1, _fn_Windy_set_on_close, windy, value);
}

////////// module net //////////
var _mod_net = external(1, "net.dll");

var _fn_WSAInit = external(1, "net.dll", "WSAInit");
function WSAInit(major, minor) {
    return external(2, 1, _fn_WSAInit, major, minor);
}

////////// module argentina //////////
var _mod_argentina = external(1, "argentina.dll");

var _fn_ArgentinaCreatCert = external(1, _mod_argentina, "ArgentinaCreatCert");
function ArgentinaCreatCert() {
    return external(2, 1, _fn_ArgentinaCreatCert);
}

var _fn_ArgentinaStart = external(1, _mod_argentina, "ArgentinaStart");
function ArgentinaStart(port) {
    return external(2, 1, _fn_ArgentinaStart, port);
}

var _fn_ArgentinaStop = external(1, _mod_argentina, "ArgentinaStop");
function ArgentinaStop() {
    return external(2, 1, _fn_ArgentinaStop);
}

var _fn_ArgentinaThreadStart = external(1, _mod_argentina, "ArgentinaThreadStart");
function ArgentinaThreadStart(port) {
    return external(2, 1, _fn_ArgentinaThreadStart, port);
}

var _fn_ArgentinaSetAppids = external(1, _mod_argentina, "ArgentinaSetAppids");
function ArgentinaSetAppids(appids) {
    return external(2, 1, _fn_ArgentinaSetAppids, appids);
}

var _fn_ArgentinaSetGaeAddr = external(1, _mod_argentina, "ArgentinaSetGaeAddr");
function ArgentinaSetGaeAddr(addr) {
    return external(2, 1, _fn_ArgentinaSetGaeAddr, addr);
}

var _fn_ArgentinaGetGaeAddr = external(1, _mod_argentina, "ArgentinaGetGaeAddr");
function ArgentinaGetGaeAddr() {
    return external(2, 1, _fn_ArgentinaGetGaeAddr);
}

var _fn_ArgentinaSetGaeAppPath = external(1, _mod_argentina, "ArgentinaSetGaeAppPath");
function ArgentinaSetGaeAppPath(path) {
    return external(2, 1, _fn_ArgentinaSetGaeAppPath, path);
}

var _fn_ArgentinaGetGaeAppPath = external(1, _mod_argentina, "ArgentinaGetGaeAppPath");
function ArgentinaGetGaeAppPath() {
    return external(2, 1, _fn_ArgentinaGetGaeAppPath);
}

var _fn_ArgentinaGetCurrentAppid = external(1, _mod_argentina, "ArgentinaGetCurrentAppid");
function ArgentinaGetCurrentAppid() {
    return external(2, 1, _fn_ArgentinaGetCurrentAppid);
}

var _fn_ArgentinaGetAppidCount = external(1, _mod_argentina, "ArgentinaGetAppidCount");
function ArgentinaGetAppidCount() {
    return external(2, 1, _fn_ArgentinaGetAppidCount);
}

var _fn_ArgentinaRemoveCurrentAppid = external(1, _mod_argentina, "ArgentinaRemoveCurrentAppid");
function ArgentinaRemoveCurrentAppid() {
    return external(2, 1, _fn_ArgentinaRemoveCurrentAppid);
}

////////// others //////////
var _fn_WinExec = external(1, "kernel32.dll", "WinExec");
function WinExec(lpCmdLine, uCmdShow) {
    return external(2, 0, _fn_WinExec, lpCmdLine, uCmdShow);
}

var _fn__waccess = external(1, "msvcrt.dll", "_waccess");
function _waccess(_Filename, _AccessMode) {
    return external(2, 1, _fn__waccess, _Filename, _AccessMode);
}

var _fn_InternetGetConnectedStateExW = external(1, "wininet.dll", "InternetGetConnectedStateExW");
function InternetGetConnectedStateExW(lpdwFlags, lpszConnectionName, dwNameLen, dwReserved) {
    return external(2, 0, _fn_InternetGetConnectedStateExW, lpdwFlags, lpszConnectionName, dwNameLen, dwReserved);
}

var _fn_InternetSetOptionW = external(1, "wininet.dll", "InternetSetOptionW");
function InternetSetOptionW(hInternet, dwOption, lpBuffer, dwBufferLength) {
    return external(2, 0, _fn_InternetSetOptionW, hInternet, dwOption, lpBuffer, dwBufferLength);
}

</script>
<script type="text/javascript" id="sc_proxysetting">
/*
typedef struct _FILETIME
    {
    DWORD dwLowDateTime;
    DWORD dwHighDateTime;
    } 	FILETIME;

typedef struct {
    DWORD   dwOption;            // option to be queried or set
    union {
        DWORD    dwValue;        // dword value for the option
        LPWSTR   pszValue;       // pointer to string value for the option
        FILETIME ftValue;        // file-time value for the option
    } Value;
} INTERNET_PER_CONN_OPTIONW, * LPINTERNET_PER_CONN_OPTIONW;

typedef struct {
    DWORD   dwSize;             // size of the INTERNET_PER_CONN_OPTION_LIST struct
    LPWSTR  pszConnection;      // connection name to set/query options
    DWORD   dwOptionCount;      // number of options to set/query
    DWORD   dwOptionError;      // on error, which option failed
    LPINTERNET_PER_CONN_OPTIONW  pOptions;
                                // array of options to set/query
} INTERNET_PER_CONN_OPTION_LISTW, * LPINTERNET_PER_CONN_OPTION_LISTW;


//
// Options used in INTERNET_PER_CONN_OPTON struct
//
#define INTERNET_PER_CONN_FLAGS                         1
#define INTERNET_PER_CONN_PROXY_SERVER                  2
#define INTERNET_PER_CONN_PROXY_BYPASS                  3
#define INTERNET_PER_CONN_AUTOCONFIG_URL                4
#define INTERNET_PER_CONN_AUTODISCOVERY_FLAGS           5
#define INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL      6
#define INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS  7
#define INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME   8
#define INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL    9

//
// PER_CONN_FLAGS
//
#define PROXY_TYPE_DIRECT                               0x00000001   // direct to net
#define PROXY_TYPE_PROXY                                0x00000002   // via named proxy
#define PROXY_TYPE_AUTO_PROXY_URL                       0x00000004   // autoproxy URL
#define PROXY_TYPE_AUTO_DETECT                          0x00000008   // use autoproxy detection

#define INTERNET_OPTION_SETTINGS_CHANGED        39
#define INTERNET_OPTION_PER_CONNECTION_OPTION   75

// sizeof_INTERNET_PER_CONN_OPTIONW = 12
// sizeof_INTERNET_PER_CONN_OPTION_LISTW = 20
*/

function setProxyOption(conn_name, option_id, string_value, dword_value, dword_value2) {
    var list_size = 20,
        option_size = 12,
        conn_name_size = conn_name && typeof(conn_name) == "string" ? (conn_name.length + 1) * 2 : 0,
        string_size = string_value && typeof(string_value) == "string" ? (string_value.length + 1) * 2 : 0;

    var buf_size = list_size +
                   option_size +
                   conn_name_size +
                   string_size;

    var buf = lmk.calloc(buf_size, 1);
    var list_p = buf,
        option_p = list_p + list_size,
        conn_name_p = conn_name_size ? option_p + option_size : 0;
        string_p = string_size ? option_p + option_size + conn_name_size : 0;

    if (conn_name_p)
        lmk.setStrw(conn_name_p, conn_name);
    if (string_p)
        lmk.setStrw(string_p, string_value);

    lmk.setDword(list_p, 20);               // list.dwSize
    lmk.setDword(list_p + 4, conn_name_p);  // list.pszConnection
    lmk.setDword(list_p + 8, 1);            // list.dwOptionCount;
    lmk.setDword(list_p + 12, 0);           // list.dwOptionError;
    lmk.setDword(list_p + 16, option_p);    // list.pOptions;

    lmk.setDword(option_p, option_id);          // option.dwOption
    if (string_p) {
        lmk.setDword(option_p + 4, string_p);   // option.Value.pszValue
    }
    else {
        if (dword_value)
            lmk.setDword(option_p + 4, dword_value);    // option.Value.dwValue
        if (dword_value2)
            lmk.setDword(option_p + 8, dword_value2);
    }

    InternetSetOptionW(0, 75, list_p, list_size);
    InternetSetOptionW(0, 39, 0, 0);

    lmk.free(buf);
}


function setProxyServer(conn_name, proxy_server) {
    setProxyOption(conn_name, 2, // INTERNET_PER_CONN_PROXY_SERVER
                   proxy_server, 0, 0);
}

function enableProxy(conn_name, enable) {
    setProxyOption(conn_name, 1, // INTERNET_PER_CONN_FLAGS
                   0, enable ? 2 : 1, 0);
}

function getConnName() {
    // INTERNET_CONNECTION_CONFIGURED  0x40
    // INTERNET_CONNECTION_LAN         0x02
    // INTERNET_CONNECTION_MODEM       0x01
    // INTERNET_CONNECTION_MODEM_BUSY  0x08
    // INTERNET_CONNECTION_OFFLINE     0x20
    // INTERNET_CONNECTION_PROXY       0x04
    var result;
    var buf = lmk.calloc(4 + 128 * 2, 1);
    var conn_flags_p = buf;
    var conn_name_p = buf + 4;
    InternetGetConnectedStateExW(conn_flags_p, conn_name_p, 127, 0);
    var conn_flags = lmk.dword(conn_flags_p);
    if (conn_flags & 0x02) {
        result = ""; // lan
    }
    else if (conn_flags & 0x01) {
        result = lmk.strw(conn_name_p);
    }
    // else result = undefined
    lmk.free(buf);
    return result;
}
</script>
<script type="text/javascript" id="sc_main">
var g_conn_name, g_running;

function id(s) {
    return document.getElementById(s);
}

function setGaeAppPath() {
    var app_path = id("app_path").value;
    if (!app_path) {
        return false;
    }
    app_path = lmk.newStra(app_path);
    ArgentinaSetGaeAppPath(app_path);
    lmk.free(app_path); // free
    return true;
}

function setGaeAddr() {
    var gae_addr = id("gae_addr").value;
    if (!gae_addr) {
        return false;
    }
    gae_addr = lmk.newStra(gae_addr);
    ArgentinaSetGaeAddr(gae_addr);
    lmk.free(gae_addr); // free
    return true;
}

function setAppids() {
    var appids = id("appids").value;
    if (!appids) {
        return false;
    }
    appids = lmk.newStra(appids);
    ArgentinaSetAppids(appids);
    lmk.free(appids); // free
    return true;
}

function start() {
    var port = Number(id("port").value);
    if (!port) {
        return false;
    }
    if (!setGaeAppPath() || !setGaeAddr() || !setAppids())
        return false;
    if (!ArgentinaThreadStart(port)) {
        return false;
    }
    return true;
}

function enableDisableProxy(b) {
    if (g_conn_name)
        enableProxy(g_conn_name, b); // modem
    enableProxy(0, b); // lan
}

function setProxyAuto() {
    if (!g_conn_name)
        g_conn_name = getConnName();

    var port = Number(id("port").value);
    if (!port)
        return;

    if (g_conn_name)
        setProxyServer(g_conn_name, "127.0.0.1:" + port); // modem
    setProxyServer(0, "127.0.0.1:" + port); // lan
    enableDisableProxy(true);
}

function setProxyMan() {
    var cmd_line = lmk.newStra("rundll32.exe shell32.dll,Control_RunDLL inetcpl.cpl,,4");
    WinExec(cmd_line, 5);
    lmk.free(cmd_line);
}

function installCert() {
    var cmd_line = lmk.newStra("certmgr.exe -add ..\\argentina.crt -c -s -r localMachine Root");
    WinExec(cmd_line, 0);
    lmk.free(cmd_line);
}

function uninstallCert() {
    var cmd_line = lmk.newStra("certmgr.exe -del -n \"Milk Line Argentina\" -c -s -r localMachine Root");
    WinExec(cmd_line, 0);
    lmk.free(cmd_line);
}

function autoConf() {
    if (g_running) {
        alert("已经在运行了");
        return;
    }
    setProxyAuto();
    if (!start())
        return;
    g_running = true;
}

var _cb_WindowOnClose = lmk.callback(0, "WindowOnClose", 5, 0, 1);
function WindowOnClose(windy, hwnd, message, wparam, lparam) {
    if (confirm("真的要退出吗？") == false)
        return 1;
    enableDisableProxy(false);
    return 0;
}

function init() {
    WSAInit(2, 2);
    if (_cb_WindowOnClose) {
        Windy_set_on_close(lmk.obj(), _cb_WindowOnClose);
    }

    if ( _waccess("..\\argentina.crt", 0) != 0 ||
            _waccess("..\\argentina.key", 0) != 0 ) {
        uninstallCert();
        if (ArgentinaCreatCert())
            installCert();
    }

    if (typeof(g_default_appids) == "string") {
        id("appids").value = g_default_appids;
    }
}

function readme() {
    if (typeof(g_readme) == "string") {
        alert(g_readme);
    }
}

function main() {
    init();

    id("show_hide_detail").onclick = function () {
        var detail = id("detail");
        if (detail.style.display == "none")
            detail.style.display = "inline";
        else
            detail.style.display = "none";
    };

    id("get_cur_appid").onclick = function () {
        alert(lmk.stra(ArgentinaGetCurrentAppid()));
    };
    id("remove_cur_appid").onclick = function () {
        ArgentinaRemoveCurrentAppid();
    };

    id("change_appids").onclick = function () {
        setAppids();
    };

    id("change_gae_app_path").onclick = function () {
        setGaeAppPath();
    };
    id("change_gae_addr").onclick = function () {
        setGaeAddr();
    };

    id("set_proxy_auto").onclick = function () {
        setProxyAuto();
    };
    id("set_proxy_man").onclick = function () {
        setProxyMan();
    };

    id("enable_proxy").onclick = function () {
        enableDisableProxy(true);
    };
    id("disable_proxy").onclick = function () {
        enableDisableProxy(false);
    };

    id("auto_conf").onclick = function () {
        autoConf();
    };

    id("install_cert").onclick = function () {
        installCert();
    }
    id("uninstall_cert").onclick = function () {
        uninstallCert();
    }

    id("readme").onclick = function () {
        readme();
    }
}
main();

</script>
</body>
</html>
